/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

function StripPound(string ) 
{
    if ( string.charAt(0) == "#") {
        return string.substring(1);
    }
    return string;
}

Vector4 = function( x, y, z, w) 
{
    this.x = x;
    this.y = y;
    this.z = z;
    this.w = w;
};


ColladaScene = function() 
{ 
    this.upAxis = "Unknown";
    this.materialMap = new Object();
    this.materialToEffectMap = new Object();
    this.textureMap = new Object();
};


ColladaScene.prototype.LoadURL = function(gl, url)
{
    var request = new XMLHttpRequest();    
    request.obj = gl;
    request.collada = this;
    request.onreadystatechange = function () {processDAE(request)};
    request.open("GET", url, true);
    request.send(null);
    return request;
    
};

function processDAE(request)
{
    var gl = request.obj;
    if ( request.readyState == 4 ) 
    {
        request.collada.LoadDAE( gl, request.responseXML.documentElement);
    }
    
}

ColladaScene.prototype.LoadDAE = function ( gl, colladaXML )
{
    this.LoadAsset(gl, colladaXML);
    this.LoadImages(gl, colladaXML);
    this.LoadMaterials(gl, colladaXML);
    this.LoadEffects(gl, colladaXML);
    
};

ColladaScene.prototype.LoadAsset = function ( gl, collada )
{
    this.upAxis = collada.getElementsByTagName("asset")[0].getElementsByTagName("up_axis")[0].firstChild.textContent;
    
};

ColladaScene.prototype.LoadMaterials = function ( gl, collada) 
{
    var library_materials = collada.getElementsByTagName("library_materials")[0];
	
    for( var materialNode = library_materials.firstElementChild; materialNode != null; materialNode = materialNode.nextElementSibling )
    {
        if ( materialNode instanceof Element )
        {
            var id = materialNode.getAttribute("id");
            var name = materialNode.getAttribute("name");
            var instance_effect = materialNode.getElementsByTagName("instance_effect")[0];
            var effectName = StripPound(instance_effect.getAttribute("url"));

            this.materialToEffectMap[id] = effectName;
        }
    }
};

ColladaScene.prototype.LoadImages = function(gl, collada) 
{
    var library_images = collada.getElementsByTagName("library_images")[0];

    for( var imageNode = library_images.firstElementChild; imageNode != null; imageNode = imageNode.nextElementSibling )
    {
        if ( imageNode instanceof Element )
        {
            var id = imageNode.getAttribute("id");
            var name = imageNode.getAttribute("name");
            var location = imageNode.getElementsByTagName("init_from")[0].textContent;
            this.textureMap[id] = location;
        }
    }

}


ColladaScene.prototype.LoadEffects = function( gl, collada )
{
    var library_effects = collada.getElementsByTagName("library_effects")[0];
    
    for( var effectNode = library_effects.firstElementChild; effectNode; effectNode = effectNode.nextElementSibling )
    {
        var id = effectNode.getAttribute("id");
        var name = effectNode.getAttribute("name");
        
        var profileNode = effectNode.getElementsByTagName("profile_COMMON")[0];
        if ( profileNode != 0 ) 
        {
            var ambientColor = new Vector4(0.25, 0.25, 0.25, 1.0);
            var diffuseColor = new Vector4(0.75, 0.75, 0.75, 1.0);
            var emissiveColor = new Vector4(0.0, 0.0, 0.0, 1.0);
            var specularColor = new Vector4(1.0, 1.0, 1.0, 1.0);
            
            var ambientTex = new Object();
            var diffuseTex = new Object();
            var emissiveTex = new Object();
            var specularTex = new Object();
            
            var surfaceToImageIdMap = new Object();
            var samplerToSurfaceMap = new Object();
            this.FindSurfaces(profileNode, surfaceToImageIdMap);
            this.FindSamplers(profileNode, samplerToSurfaceMap);
            
            var techniqueNode = profileNode.getElementsByTagName("technique")[0];
            if (techniqueNode != null)
            {
                var typeNode = techniqueNode.getElementsByTagName("blinn")[0];
                if (typeNode == null) {typeNode = techniqueNode.getElementsByTagName("phong")[0];}
                if (typeNode == null) {typeNode = techniqueNode.getElementsByTagName("lambert")[0];}
                if (typeNode != null)
                {
                    var ambientNode = typeNode.getElementsByTagName("ambient")[0];
                    var diffuseNode = typeNode.getElementsByTagName("diffuse")[0];
                    var emissiveNode = typeNode.getElementsByTagName("emissive")[0];
                    var specularNode = typeNode.getElementsByTagName("specular")[0];
                    
                    var shininessNode = typeNode.getElementsByTagName("shininess")[0];
                    var reflectiveNode = typeNode.getElementsByTagName("reflective")[0];
                    var reflectivityNode = typeNode.getElementsByTagName("reflectivity")[0];
                    var transparencyNode = typeNode.getElementsByTagName("transparency")[0];
                    
                    
                    //Get the color or the texture.
                    if (!this.TryGetColor(ambientNode, ambientColor)) {this.TryGetTexture(ambientNode, ambientTex);}
                    if (!this.TryGetColor(diffuseNode, diffuseColor)) {this.TryGetTexture(diffuseNode, diffuseTex);}
                    if (!this.TryGetColor(emissiveNode, emissiveColor)) {this.TryGetTexture(emissiveNode, emissiveTex);}
                    if (!this.TryGetColor(specularNode, specularColor)) {this.TryGetTexture(specularNode, specularTex);}
                    
                    //Get Surfaces:
                    if (diffuseTex.Found) {diffuseTex.TextureFileLocation = samplerToSurfaceMap[diffuseTex.TextureFileLocation];}
                    if (ambientTex.Found) {ambientTex.TextureFileLocation = samplerToSurfaceMap[ambientTex.TextureFileLocation];}
                    if (emissiveTex.Found) {emissiveTex.TextureFileLocation = samplerToSurfaceMap[emissiveTex.TextureFileLocation];}
                    if (specularTex.Found) {specularTex.TextureFileLocation = samplerToSurfaceMap[specularTex.TextureFileLocation];}
                    
                    //Get Image Ids:
                    if (diffuseTex.Found) {diffuseTex.TextureFileLocation = surfaceToImageIdMap[diffuseTex.TextureFileLocation];}
                    if (ambientTex.Found) {ambientTex.TextureFileLocation = surfaceToImageIdMap[ambientTex.TextureFileLocation];}
                    if (emissiveTex.Found) {emissiveTex.TextureFileLocation = surfaceToImageIdMap[emissiveTex.TextureFileLocation];}
                    if (specularTex.Found) {specularTex.TextureFileLocation = surfaceToImageIdMap[specularTex.TextureFileLocation];}
                    
                    //Get Image file:
                    if (diffuseTex.Found) {diffuseTex.TextureFileLocation = this.textureMap[diffuseTex.TextureFileLocation];}
                    if (ambientTex.Found) {ambientTex.TextureFileLocation = this.textureMap[ambientTex.TextureFileLocation];}
                    if (emissiveTex.Found) {emissiveTex.TextureFileLocation = this.textureMap[emissiveTex.TextureFileLocation];}
                    if (specularTex.Found) {specularTex.TextureFileLocation = this.textureMap[specularTex.TextureFileLocation];}
                }
            }
            
            //TODO: Move to a manager
            var material = new Object();
            material.ambientColor = ambientColor;
            material.diffuseColor = (diffuseColor);
            material.emissiveColor = (emissiveColor);
            material.specularColor = (specularColor);
            material.name = (name);
            
            //Textures:
            if (diffuseTex.Found) 
            {
                /*
                Stream * tx = new FileObject(diffuseTex.TextureFileLocation);
                Texture2 * tex0 = TextureManager::getInstance().CreateTexture(*tx);
                
                if ( tex0 != NULL )
                {
                    material.setTexture(0, tex0);
                    tex0.setWrapU( diffuseTex.WrapU);
                    tex0.setWrapV( diffuseTex.WrapV);
                    material.setNormalBlend(tex0.isBlendRequired());
                    material.setTransformTex0(Matrix4(TRANS, diffuseTex.OffsetU, diffuseTex.OffsetV, 0.0f));
                    
                    if ( diffuseTex.TileScaleU != 0 ) 
                    {
                        material.getTransformTex0().m00 = 1.0f / diffuseTex.TileScaleU;
                    }
                    
                    if ( diffuseTex.TileScaleV != 0 ) 
                    {
                        material.getTransformTex0().m11 = 1.0f / diffuseTex.TileScaleV;
                    }
                }
                delete tx;
                */
            }
            /*if (ambientTex.Found) 
			{
				Stream * tx = new FileObject(ambientTex.TextureFileLocation);
				Texture2 * tex1 = TGALoader::LoadTGA(*tx);
            
				material.setTexture(1, tex1);
				tex1.setWrapU( diffuseTex.WrapU);
				tex1.setWrapV( diffuseTex.WrapV);
				material.setNormalBlend(tex1.isBlendRequired());
				material.setTransformTex1( Matrix4(TRANS, ambientTex.OffsetU, ambientTex.OffsetV, 0.0f));
            
				if ( ambientTex.TileScaleU != 0 ) 
				{
					material.getTransformTex1().m00 = 1.0f / ambientTex.TileScaleU;
				}
            
				if ( ambientTex.TileScaleV != 0 ) 
				{
					material.getTransformTex1().m11 = 1.0f / ambientTex.TileScaleV;
				}
				delete tx;
			}*/
            
            //Don't care right now
            //if (emissiveTex.Found) { emissiveTex.TextureFileLocation = textureMap[emissiveTex.TextureFileLocation]; }
            //if (specularTex.Found) { specularTex.TextureFileLocation = textureMap[specularTex.TextureFileLocation]; }
            
            this.materialMap[name] = material;
            
        }
    }
}

ColladaScene.prototype.FindSurfaces = function(profileNode, surfaceToImageIdMap )
{
    var newparamNodeList = profileNode.getElementsByTagName("newparam")[0];
    
    for( var newparamNode = newparamNodeList; newparamNode; newparamNode = newparamNode.nextElementSibling)
    {
        var childNode = newparamNode.getElementsByTagName("surface")[0];
        if (childNode != null )
        {
            var textureType = childNode.getAttribute("type");
            
            var initNode = childNode.getElementsByTagName("init_from")[0];
            if (initNode != null)
            {
                var surfaceID = newparamNode.getAttribute("sid");
                var initFrom = initNode.textContent;
                surfaceToImageIdMap[surfaceID] = initFrom;
            }
        }
    }
}

ColladaScene.prototype.FindSamplers = function(profileNode, samplerToSurfaceMap)
{
    var newparamNodeList = profileNode.getElementsByTagName("newparam")[0];
    
    for( var newparamNode = newparamNodeList; newparamNode; newparamNode = newparamNode.nextElementSibling )
    {	
        var childNode = newparamNode.getElementsByTagName("sampler2D")[0];
        //or sampler3D
        //or samplerCUBE
        if ( childNode != null )
        {
            var sourceNode = childNode.getElementsByTagName("source")[0];
            if (sourceNode != null)
            {
                var samplerID = newparamNode.getAttribute("sid");
                var surfaceSource = sourceNode.textContent;
                samplerToSurfaceMap[samplerID] = surfaceSource;
            }
        }
    }
}

ColladaScene.prototype.TryGetColor = function(channelTypeNode, outputColor)
{
    if (channelTypeNode != null)
    {
        var result = false;
        var colorNode = channelTypeNode.getElementsByTagName("color")[0];
        if ( colorNode != null )
        {            
            var colorStr = colorNode.textContent;
            parts = colorStr.split(" ");
            
            if ( parts.length >= 3 ) 
            {
                outputColor.x = parseFloat(parts[0]);
                outputColor.y = parseFloat(parts[1]);
                outputColor.z = parseFloat(parts[2]);
            }
            if ( parts.length >= 4 )
            {
                outputColor.w = parseFloat(parts[3]);
            }                        
            
            result = true;
        }
        
        return result;
    }
    
    return false;
}

ColladaScene.prototype.TryGetTexture = function(channelTypeNode, textureInfo)
{
    var result = false;
    if (channelTypeNode != null)
    {
        var textureNode = channelTypeNode.getElementsByTagName("texture")[0];
        if (textureNode != null)
        {
            var samplerName = textureNode.getAttribute("texture");
            var uvSet = textureNode.getAttribute("texcoord");
            
            textureInfo.TextureFileLocation = samplerName;
            textureInfo.TextureUVSet = uvSet;
            textureInfo.Found = true;
            result = true;
            
            var extraTexNode = textureNode.getElementsByTagName("extra")[0];
            if (extraTexNode != null)
            {
                var techniqueNodes = extraTexNode.getElementsByTagName("technique")[0];
                for( var techniqueNode = techniqueNodes; techniqueNode; techniqueNode = techniqueNode.nextElementSibling )
                {
                    var profile = techniqueNode.getAttribute("profile");
                    if ( profile == "MAYA")
                    {
                        var offsetU;
                        var offsetV;
                        var rotateW;
                        var tileU;
                        var tileV;
                        
//                        textureInfo.MirrorU = ParseBoolean(techniqueNode.getElementsByTagName("mirrorU")[0]);
//                        textureInfo.MirrorV = ParseBoolean(techniqueNode.getElementsByTagName("mirrorV")[0]);
//                        textureInfo.WrapU = ParseBoolean(techniqueNode.getElementsByTagName("wrapU")[0]);
//                        textureInfo.WrapV = ParseBoolean(techniqueNode.getElementsByTagName("wrapV")[0]);
                        
//                        if ( ParseFloat(techniqueNode.getElementsByTagName("repeatU")[0], tileU) )
//                        {
//                            textureInfo.TileScaleU = tileU;
//                        }
//                        if ( ParseFloat(techniqueNode.getElementsByTagName("repeatV")[0], tileV) )
//                        {
//                            textureInfo.TileScaleV = tileV;
//                        }
//                        
//                        if ( ParseFloat(techniqueNode.getElementsByTagName("offsetU")[0], offsetU) )
//                        {
//                            textureInfo.OffsetU = offsetU;
//                        }
//                        if ( ParseFloat(techniqueNode.getElementsByTagName("offsetV")[0], offsetV) )
//                        {
//                            textureInfo.OffsetV = offsetV;
//                        }
//                        if (ParseFloat(techniqueNode.getElementsByTagName("rotateUV")[0], rotateW) )
//                        {
//                            textureInfo.RotationW = rotateW;
//                        }
                        
                    }
                }
            }
        }
    }
    return result;
}






//GEOMETRY
//
//ColladaScene.prototype.LoadGeometries = function(gl, collada)
//{
//	var library_geometries = collada.getElementsByTagName("library_geometries")[0];
//	
//	for( var geometryNode = library_geometries.firstElementChild; geometryNode; geometryNode = geometryNode.nextElementSibling )
//	{
//		string id = geometryNode.getAttribute("id");
//		string name = geometryNode.getAttribute("name");
//
//		var meshNodes = geometryNode.getElementsByTagName("mesh")[0];
//		for( var meshNode = meshNodes; meshNode; meshNode = meshNode.nextElementSibling )
//		{
//			vector<float> originalVerts;
//			vector<float> originalNormals;
//			vector<float> originalColors;
//			vector<float> originalTangents;
//			vector<float> originalBiTangents;
//			
//			vector<int> originalVertexIndex;
//			vector<int> originalNormalIndex;
//			vector<int> originalColorIndex;
//			vector<int> originalTangentIndex;
//			vector<int> originalBiTangentIndex;
//			vector<vector<int>> originalUVIndex;
//			vector<vector<float>> originalMainUVs;
//			bool perVertexNormals = true;
//
//			map<string, vector<float>> sourceMapFloats;
//			map<string, int> sourceParamCount;
//
//			MapSources(meshNode, &sourceParamCount, &sourceMapFloats, NULL);
//
//			var meshChildNodes = meshNode.firstElementChild;
//			for( var meshChild = meshChildNodes; meshChild; meshChild = meshChild.nextElementSibling )
//			{
//				if ( meshChild.Value() == string("vertices") )
//				{
//					//This can be either POSITION or POSITION AND NORMAL
//					//This is the difference between PerVertex and PerFace normals!! (SMOOTHING GROUPS)
//					var inputs = meshChild.firstElementChild;
//					for( var inputNode = inputs; inputNode; inputNode = inputNode.nextElementSibling )
//					{
//						string semantic = inputNode.getAttribute("semantic");
//						string sourceInput = StripPound(inputNode.getAttribute("source"));
//
//						if (semantic == string("POSITION"))
//						{
//							originalVerts = sourceMapFloats[sourceInput];
//							if (this.upAxis == Z_Axis )
//							{
//								ConvertAxis(originalVerts);
//							}
//						}
//						else if (semantic == string("NORMAL"))
//						{
//							originalNormals = sourceMapFloats[sourceInput];
//							if (this.upAxis == Z_Axis )
//							{
//								ConvertAxis(originalNormals);
//							}
//						}
//					}
//				}
//				// #################################################
//				// ########### READING TRIANGLES!!!#################
//				// #################################################
//				else if (meshChild.Value() == string("triangles"))
//				{
//					var trianglesNode = meshChild;
//
//					//There might be some materials here... Kinda stupid, it should be on the instance, but its not.
//					string materialName = trianglesNode.getAttribute("material");
//					
//					int triangleCount = atoi(trianglesNode.getAttribute("count"));
//					vector<int> uvCount;
//					int colorCount = 0;
//
//					//Our Index List...
//					var pNode = trianglesNode.getElementsByTagName("p")[0];
//					vector<long> offsetIndices;
//					ParseLongArray(pNode, offsetIndices);
//
//					int inputCount = 0;
//					var inputs = trianglesNode.getElementsByTagName("input")[0];
//					for( var triangleInputNode = inputs; triangleInputNode; triangleInputNode = triangleInputNode.NextSibling("input") )
//					{
//						inputCount++;
//					}
//
//					//Put it all together:
//					for( var triangleInputNode = inputs; triangleInputNode; triangleInputNode = triangleInputNode.NextSibling("input") )
//					{
//						string semantic = triangleInputNode.getAttribute("semantic");
//						string sourceInput = StripPound(triangleInputNode.getAttribute("source"));
//
//						int offset = atoi(triangleInputNode.getAttribute("offset"));
//
//						if (semantic == string("VERTEX"))
//						{
//							for (int i = 0; i < (int)triangleCount * 3; i++)
//							{
//								originalVertexIndex.push_back((int)offsetIndices[(i * inputCount) + offset]);
//							}
//						}
//						else if (semantic == string("NORMAL"))
//						{
//							//Just do this once: This means it is PER FACE normals
//							if (originalNormals.size() == 0)
//							{
//								originalNormals = sourceMapFloats[sourceInput];
//								if (this.upAxis == Z_Axis )
//								{
//									ConvertAxis(originalNormals);
//								}
//							}
//							perVertexNormals = false;	//Its per face
//							for (int i = 0; i < (int)triangleCount * 3; i++)
//							{
//								originalNormalIndex.push_back((int)offsetIndices[(i * inputCount) + offset]);
//							}
//						}
//						else if (semantic == string("COLOR"))
//						{
//							//Do this only once this means per face normals
//							if (originalColors.size() == 0)
//							{
//								originalColors = sourceMapFloats[sourceInput];
//								colorCount = sourceParamCount[sourceInput];
//							}
//
//							for (int i = 0; i < (int)triangleCount * 3; i++)
//							{
//								originalColorIndex.push_back((int)offsetIndices[(i * inputCount) + offset]);
//							}
//						}
//						else if (semantic == string("TEXCOORD"))
//						{
//							//CS PPL start at 0
//							string setStr = triangleInputNode.getAttribute("set");
//							if (setStr.size() == 0 ) { setStr = "1"; }
//							int set = atoi(setStr.c_str()) - 1;
//
//							originalMainUVs.push_back(sourceMapFloats[sourceInput]);
//							originalUVIndex.push_back(vector<int>());
//							uvCount.push_back(sourceParamCount[sourceInput]);
//
//							for (int i = 0; i < (int)triangleCount * 3; i++)
//							{
//								int index = (int)offsetIndices[(i * inputCount) + offset];
//								originalUVIndex[set].push_back(index);
//							}
//						}
//						else if (semantic == string("TEXTANGENT"))
//						{
//							//CS PPL start at 0
//							string setStr = triangleInputNode.getAttribute("set");
//							if (setStr.size() == 0 ) { setStr = "1"; }
//							int set = atoi(setStr.c_str()) - 1;
//							UNREFERENCED_PARAMETER(set);
//
//							//Do this only once this means per face normals
//							if (originalTangents.size() == 0 )
//							{
//								originalTangents = sourceMapFloats[sourceInput];
//							}
//
//							for (int i = 0; i < (int)triangleCount * 3; i++)
//							{
//								originalTangentIndex.push_back((int)offsetIndices[(i * inputCount) + offset]);
//							}
//						}
//						else if (semantic == string("TEXBINORMAL"))
//						{
//							//CS PPL start at 0
//							string setStr = triangleInputNode.getAttribute("set");
//							if (setStr.size() == 0 ) { setStr = "1"; }
//							int set = atoi(setStr.c_str()) - 1;
//							UNREFERENCED_PARAMETER(set);
//
//							//Do this only once this means per face normals
//							if (originalBiTangents.size() == 0 )
//							{
//								originalBiTangents = sourceMapFloats[sourceInput];
//							}
//
//							for (int i = 0; i < (int)triangleCount * 3; i++)
//							{
//								originalBiTangentIndex.push_back((int)offsetIndices[(i * inputCount) + offset]);
//							}
//						}
//					}
//					//Load up the triangle complete.
//
//					//Bring in the Skin Info too if its needed: (SKINNING NOT IMPLEMENTED
//
//					//Finished reading Triangle Inputs we now should know enough to make the geometry.
//					//Reorder to Vertex order:
//					GraphicsArray<float> * verts = new GraphicsArray<float>((int)triangleCount * 3 * 3);		//3 floats per vert, 3 verts per triangle
//					GraphicsArray<float> * normals = NULL;
//					GraphicsArray<float> * mainUVs = NULL;
//					GraphicsArray<float> * colors = NULL;
//					GraphicsArray<unsigned short> * indices = new GraphicsArray<unsigned short>((int)triangleCount * 3);		//3 indicies per triangle.
//					GraphicsArray<float> * tangents = NULL;
//					GraphicsArray<float> * biTangents = NULL;
//
//					if (originalNormals.size() != 0)
//					{
//						normals = new GraphicsArray<float>((int)triangleCount * 3 * 3);		//3 floats per noaml, 3 normals per triangle
//					}
//
//					if (originalMainUVs.size() != 0 )
//					{
//						mainUVs = new GraphicsArray<float>((int)triangleCount * 3 * 2);		//2 floats per UV, 3 uvs per triangle.
//					}
//
//					if (originalColors.size() != 0 )
//					{
//						if (colorCount == 4)
//						{
//							colors = new GraphicsArray<float>((int)triangleCount * 3 * 4);		//4 floats per color, 3 colors per triangle
//							colors.setElementCount(4);
//						}
//						else if (colorCount == 3)
//						{
//							colors = new GraphicsArray<float>((int)triangleCount * 3 * 3);		//3 floats per color, 3 colors per triangle
//							colors.setElementCount(3);
//						}
//						else
//						{
//							throw new Exception("Colors must have at least 3 values, at most 4");
//						}
//					}
//
//					if (originalTangents.size() != 0 )
//					{
//						tangents = new GraphicsArray<float>((int)triangleCount * 3 * 3);		//3 floats per bi/tangent, 3 normals per triangle
//					}
//
//					if (originalBiTangents.size() != 0 )
//					{
//						biTangents = new GraphicsArray<float>((int)triangleCount * 3 * 3);		//3 floats per bi/tangent, 3 normals per triangle
//					}
//
//					//Why not store the local bounding box while we're here
//					float maxValues[3];
//					float minValues[3];
//					maxValues[0] = FLT_MIN;
//					maxValues[1] = FLT_MIN;
//					maxValues[2] = FLT_MIN;
//					minValues[0] = FLT_MAX;
//					minValues[1] = FLT_MAX;
//					minValues[2] = FLT_MAX;
//
//
//					//We are flattening the vert info, this is not exactly optimal, but its easier
//					//Very easily could go an optimization pass afterwords and use overlapping indices.
//					for (int i = 0; i < (int)triangleCount * 3; i++)
//					{
//						indices.ToArray()[i] = (short)i;
//						verts.ToArray()[i * 3 + 0] = originalVerts[(int)originalVertexIndex[i] * 3 + 0];
//						verts.ToArray()[i * 3 + 1] = originalVerts[(int)originalVertexIndex[i] * 3 + 1];
//						verts.ToArray()[i * 3 + 2] = originalVerts[(int)originalVertexIndex[i] * 3 + 2];						
//
//						for (int v = 0; v < 3; v++)
//						{
//							if (verts.ToArray()[i * 3 + v] > maxValues[v])
//							{
//								maxValues[v] = verts.ToArray()[i * 3 + v];
//							}
//							if (verts.ToArray()[i * 3 + v] < minValues[v])
//							{
//								minValues[v] = verts.ToArray()[i * 3 + v];
//							}
//						}
//
//						if (originalNormals.size() != 0)
//						{
//							if (perVertexNormals)
//							{
//								normals.ToArray()[i * 3 + 0] = originalNormals[(int)originalVertexIndex[i] * 3 + 0];
//								normals.ToArray()[i * 3 + 1] = originalNormals[(int)originalVertexIndex[i] * 3 + 1];
//								normals.ToArray()[i * 3 + 2] = originalNormals[(int)originalVertexIndex[i] * 3 + 2];
//							}
//							else
//							{
//								normals.ToArray()[i * 3 + 0] = originalNormals[(int)originalNormalIndex[i] * 3 + 0];
//								normals.ToArray()[i * 3 + 1] = originalNormals[(int)originalNormalIndex[i] * 3 + 1];
//								normals.ToArray()[i * 3 + 2] = originalNormals[(int)originalNormalIndex[i] * 3 + 2];
//							}
//						}
//
//						if (originalMainUVs.size() != 0)
//						{
//							int uvSize = uvCount[0];
//
//							mainUVs.ToArray()[i * 2 + 0] = originalMainUVs[0][(int)originalUVIndex[0][i] * uvSize + 0];
//							mainUVs.ToArray()[i * 2 + 1] = originalMainUVs[0][(int)originalUVIndex[0][i] * uvSize + 1];
//
//							//This is where one might add multi-uv support...
//						}
//
//						if (originalColors.size() != 0)
//						{
//							colors.ToArray()[i * colorCount + 0] = originalColors[(int)originalColorIndex[i] * colorCount + 0];
//							colors.ToArray()[i * colorCount + 1] = originalColors[(int)originalColorIndex[i] * colorCount + 1];
//							colors.ToArray()[i * colorCount + 2] = originalColors[(int)originalColorIndex[i] * colorCount + 2];
//							if (colorCount == 4)
//							{
//								colors.ToArray()[i * colorCount + 3] = originalColors[(int)originalColorIndex[i] * colorCount + 3];
//							}
//						}
//
//						if (originalTangents.size() != 0)
//						{
//							tangents.ToArray()[i * 3 + 0] = originalTangents[(int)originalTangentIndex[i] * 3 + 0];
//							tangents.ToArray()[i * 3 + 1] = originalTangents[(int)originalTangentIndex[i] * 3 + 1];
//							tangents.ToArray()[i * 3 + 2] = originalTangents[(int)originalTangentIndex[i] * 3 + 2];
//						}
//
//						if (originalBiTangents.size() != 0)
//						{
//							biTangents.ToArray()[i * 3 + 0] = originalBiTangents[(int)originalBiTangentIndex[i] * 3 + 0];
//							biTangents.ToArray()[i * 3 + 1] = originalBiTangents[(int)originalBiTangentIndex[i] * 3 + 1];
//							biTangents.ToArray()[i * 3 + 2] = originalBiTangents[(int)originalBiTangentIndex[i] * 3 + 2];
//						}
//
//					}	//END trigangle flattening
//					
//					if (verts != NULL )
//					{
//						GraphicsObjectGeometry * geom = new GraphicsObjectGeometry(verts, mainUVs, 0,0,0, normals, colors, indices);
//						geom.setName(id);
//						geom.setDefaultMaterial(materialName);
//						geometryMap[id].push_back(geom);
//						geom.ComputeBoundingSphere();
//					}
//				}
//			}			
//		}
//	}
//}

ColladaScene.prototype.LoadSceneGraph = function(gl, collada)
{
	var library_visual_scenes = collada.getElementsByTagName("library_visual_scenes")[0];
	
	for( var visual_scene = library_visual_scenes.firstElementChild; visual_scene; visual_scene = visual_scene.nextElementSibling )
	{
		var nodeList = visual_scene.getElementsByTagName("node")[0];
		for( var nodeNode = nodeList; nodeNode; nodeNode = nodeNode.nextElementSibling )
		{
                  if ( nodeNode.localName == "node")
			this.LoadNode(nodeNode);
		}
	}
}

//ColladaScene.prototype.LoadNode = function( nodeNode)
//{
//      var transform = new CanvasMatrix4();
//	var translation = new Vector4(0,0,0,1);
//	var rotation = new Vector4(0,0,0,0);
//	var scale = new Vector4(1,1,1,1);
//
//	var name = nodeNode.getAttribute("id");
//	var id = nodeNode.getAttribute("sid");
//	var type = nodeNode.getAttribute("type");
//
//	//The bind shape unrotates the verts back to z_up:
//	var unRotate90 = Matrix4(1.0f, 0.0f, 0.0f, 0.0f,
//								0.0f, 0.0f, 1.0f, 0.0f,
//								0.0f, -1.0f, 0.0f, 0.0f,
//								0.0f, 0.0f, 0.0f, 1);
//	var rotate90 = Matrix4(1.0f, 0.0f, 0.0f, 0.0f,
//								0.0f, 0.0f, -1.0f, 0.0f,
//								0.0f, 1.0f, 0.0f, 0.0f,
//								0.0f, 0.0f, 0.0f, 1.0f);
//
//	
//	if (ParseVector4(nodeNode.getElementsByTagName("scale")[0], scale))
//	{
//		transform *= Matrix4(SCALE, scale[x], scale[y], scale[z]);
//	}
//
//	var rotationList = nodeNode.getElementsByTagName("rotate")[0];
//	for( var rotationNode = rotationList; rotationNode; rotationNode = rotationNode.NextSibling("rotate") )
//	{	
//		if ( ParseVector4(rotationNode, rotation))
//		{
//			if (this.upAxis == Z_Axis)
//			{
//				float tempY = rotation[Y];
//				rotation[Y] = rotation[Z];
//				rotation[Z]= -tempY;
//			}
//
//			Matrix4 rotMat = Matrix4::MatrixFromAxisAngle(Vector4(rotation[X], rotation[Y], rotation[Z]), MathUtil::ToRadians(rotation[W]));
//			transform *= rotMat;
//		}
//	}
//
//	if (ParseVector4(nodeNode.getElementsByTagName("translate")[0], translation))
//	{
//		if (this.upAxis == Z_Axis)
//		{
//			float tempY = translation[Y];
//			translation[Y] = translation[Z];
//			translation[Z] = -tempY;
//		}
//
//		transform *= Matrix4(TRANS, translation[x], translation[y], translation[z]);
//	}
//
//	
//
//	//TODO: Read in just a pure Matrix type:
//
//
//	//Get other stuff.
//	var instance_geometryList = nodeNode.getElementsByTagName("instance_geometry")[0];
//	var extraList = nodeNode.getElementsByTagName("extra")[0];
//
//	int i = 0;
//	vector<GraphicsObject*> loadedGeoms;
//	for( var instanceGeometryNode = instance_geometryList; instanceGeometryNode; instanceGeometryNode = instanceGeometryNode.NextSibling("instance_geometry") )
//	{
//		string instanceName = name;
//		if (i != 0)
//		{
//			char tmp[5];
//			_itoa_s(i, tmp, 5, 10);
//			instanceName += tmp;
//		}
//		LoadInstanceGeometry(instanceName, instanceGeometryNode, transform, loadedGeoms);
//		i++;
//	}
//
//	for( var extraNode = extraList; extraNode; extraNode = extraNode.NextSibling("extra") )
//	{
//		var techniqueList = extraNode.getElementsByTagName("technique")[0];
//		for( var techNode = techniqueList; techNode; techNode = techNode.NextSibling("technique") )
//		{
//			var userNode = techNode.getElementsByTagName("user_properties")[0];
//			if ( userNode != NULL )
//			{
//				string userProp = userNode.firstElementChild.Value();
//				int addIndex = userProp.find("BLEND=ADD");
//				int normIndex = userProp.find("BLEND=NORMAL");
//				if ( addIndex >= 0 )
//				{
//					for ( vector<GraphicsObject*>::iterator it = loadedGeoms.begin(); it != loadedGeoms.end(); it++ )
//					{
//						GraphicsObject * obj = *it;
//						obj.getMaterial().setAdditiveBlend(true);
//					}
//				}
//				if ( normIndex >= 0 )
//				{
//					for ( vector<GraphicsObject*>::iterator it = loadedGeoms.begin(); it != loadedGeoms.end(); it++ )
//					{
//						GraphicsObject * obj = *it;
//						obj.getMaterial().setNormalBlend(true);
//					}
//				}
//			}
//		}
//	}
//}
//
//ColladaScene.prototype.LoadInstanceGeometry = function( gl, var instanceName, var instanceGeometryNode, var worldMat, var loadedGeoms)
//{
//	if (instanceGeometryNode != null)
//	{
//		var url = StripPound(instanceGeometryNode.getAttribute("url"));
//		
//              var geoms = geometryMap[url]; 
//
//		int i =0;
//		for ( var model in geoms )
//		{
//			i++;
//			//TODO: Not quite done yet.
//                      var instance = new GraphicsObject(model, 0 );

//			if ( i > 1 )
//			{
//				instance.name = (instanceName + new String(i));
//			}
//			else
//			{
//				instance.name = (instanceName);
//			}
//
//			if (model.getDefaultMaterial().size() == 0 )
//			{
//				//No material on this!
//				instance.material = (new Material());
//				materialMap["OMG-Default"] = instance.material;
//			}
//			/*else if ( materialMap[model.getDefaultMaterial()] != null )
//			{
//				instance.material = (materialMap[model.getDefaultMaterial()]);
//			}*/
//			else
//			{
//				//In this case, this instance has a specific Material binding, we will replace the "default"
//				//With the requested material.
//				var bindMaterial = instanceGeometryNode.getElementsByTagName("bind_material")[0];
//				var technique = bindMaterial.getElementsByTagName("technique_common")[0];
//				var instanceMaterialNode = technique.getElementsByTagName("instance_material")[0];
//
//				var symbol = StripPound(instanceMaterialNode.getAttribute("symbol"));
//				var target = StripPound(instanceMaterialNode.getAttribute("target"));
//
//				if (model.getDefaultMaterial() == symbol && materialMap[target] != null)
//				{
//					instance.setMaterial(materialMap[target]);
//				}
//				else
//				{
//					//Not found, we'll use the defaults.
//					instance.setMaterial(materialMap[model.getDefaultMaterial()]);
//
//					if ( instance.getMaterial() == 0 )
//					{
//						//cout << "Warning: Missing material: " << model.getDefaultMaterial() << " on " << instanceName << endl;
//						instance.material = (new Material());
//					}
//
//					//instance.material = (new Material());
//				}
//			}
//			
//			instance.WorldMatrix = (worldMat);
//			instanceMap[instance.getName()] = instance;
//			loadedGeoms.add(instance);
//		}
//	}
//}


//UTILS:
ColladaScene.prototype.ParseBoolean = function( booleanNode)
{
    var result = false;
    if ( booleanNode != null && booleanNode.firstElementChild != null )
    {
        if ( booleanNode.textContent != null )
        {
            var value = booleanNode.textContent;
            if ( value == "1" || value == "true" || value == "TRUE" )
            {
                result = true;
            }
        }
    }
    return result;
}

ColladaScene.prototype.ParseFloat = function( floatNode, outFloatValue)
{
    var result = false;
    if ( floatNode != null && floatNode.firstElementChild != null )
    {
        if ( floatNode.firstElementChild.Value() != null )
        {
            var value = floatNode.textContent;

            outFloatValue.value = parseFloat(value);
            {
                result = true;
            }
        }
    }
    return result;
}

ColladaScene.prototype.ParseVector4 = function( vectorNode, vectorOutValue)
{
    var result = false;
    if ( vectorNode != null && vectorNode.firstElementChild != null )
    {
        if ( vectorNode.textContent != NULL )
        {
            var value = vectorNode.textContent;

            parts = value.split(" ");

            if ( parts.length >= 3 ) 
            {
                vectorOutValue.x = parseFloat(parts[0]);
                vectorOutValue.y = parseFloat(parts[1]);
                vectorOutValue.z = parseFloat(parts[2]);
                vectorOutValue.w = 1.0;
            }
            if ( parts.length >= 4 )
            {
                vectorOutValue.w = parseFloat(parts[3]);
            }			
        }
    }
    return result;
}

ColladaScene.prototype.ParseFloatArray = function( floatArrayNode, outFloatArrayValue)
{
    var result = false;
    if ( floatArrayNode != null && floatArrayNode.firstElementChild != null )
    {
        if ( floatArrayNode.textContent != null )
        {
            var value = floatArrayNode.textContent;
            var arrayList = value.split(" ");
                        
            for ( var part in arrayList )
            {
                var partValue = parseFloat(part);
                outFloatArrayValue.push(partValue);   
            }
        }
    }
    return result;
}

ColladaScene.prototype.ParseLongArray = function( arrayNode, outLongArrayValue)
{
    var result = false;
    if ( arrayNode != null && arrayNode.firstElementChild != null )
    {
        if ( arrayNode.textContent != null )
        {
            var valueStr = arrayNode.textContent;
            var arrayList = valueStr.split(" ");
                        
            for ( var part in arrayList )
            {
                var partValue = parseLong(part);
                outLongArrayValue.push(partValue);   
            }
        }
    }
    return result;
}

//void ColladaMiniLoader::MapSources(var node, map<string, int> * sourceParamCount, map<string, vector<float>> * sourceMapFloats, map<string, vector<string>> * sourceMapNames)
//{
//	var sourceNodes = node.getElementsByTagName("source")[0];
//	for( var sourceNode = sourceNodes; sourceNode; sourceNode = sourceNode.NextSibling("source") )
//	{
//		string sourceID = sourceNode.getAttribute("id");
//		var sourceChildNodes = sourceNode.firstElementChild;
//
//		for( var sourceChildNode = sourceChildNodes; sourceChildNode; sourceChildNode = sourceChildNode.nextElementSibling )
//		{
//			if ( sourceMapFloats != NULL && sourceChildNode.Value() == string("float_array"))
//			{
//				vector<float> data;
//				if ( ParseFloatArray(sourceChildNode, data) )
//				{
//					(*sourceMapFloats)[sourceID] = data;
//				}
//			}
//			else if (sourceChildNode.Value() == string("name_array"))
//			{
//				UNREFERENCED_PARAMETER(sourceMapNames);
//				//string[] data = ColladaUtil.ParseNameArray(sourceChildNode);
//				//sourceMapNames[sourceID] = data;
//			}
//
//			if ( sourceParamCount != NULL )
//			{
//				int count = 0;
//				var tech = sourceNode.getElementsByTagName("technique_common")[0];
//				var access = tech.getElementsByTagName("accessor")[0];
//				var params = access.getElementsByTagName("param")[0];
//				for( var param = params; param; param = param.nextElementSibling )
//				{
//					count++;
//				}
//
//				(*sourceParamCount)[sourceID] = count;
//			}
//
//		}
//	}
//}
//
//
ColladaScene.prototype.ConvertAxis = function(arrayData)
{
    for (var i = 0; i < arrayData.length; i += 3)
    {
        var tempY = arrayData[i + 1];
		arrayData[i + 1] = arrayData[i + 2];
		arrayData[i + 2] = -tempY;
    }
}

